package com.sky.service.impl;

import com.sky.context.BaseContext;
import com.sky.dto.ReservationDTO;
import com.sky.entity.BookingOrder;
import com.sky.entity.MeetingRoom;
import com.sky.entity.Payment;
import com.sky.exception.OutTimeException;
import com.sky.exception.PaymentNotFoundException;
import com.sky.mapper.BookingOrderMapper;
import com.sky.mapper.MeetingRoomMapper;
import com.sky.mapper.PaymentMapper;
import com.sky.service.PaymentService;
import com.sky.service.ReservationService;
import com.sky.vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentMapper paymentMapper;
    @Autowired
    private  BookingOrderMapper bookingOrderMapper;
    @Autowired
    private MeetingRoomMapper meetingRoomMapper;

    /**
     * 用户支付订单
     * @param orderId
     * @param paymentMethod
     */
    @Override
    @Transactional
    public void payOrder(Long orderId, String paymentMethod) {
        Payment payment1=paymentMapper.getByOrderId(orderId);


        //先修改支付表
        Payment payment=Payment.builder()
                .id(payment1.getId())
                .paymentMethod(paymentMethod)
                .paymentStatus("已支付")
                .paymentTime(LocalDateTime.now())
                .build();
        paymentMapper.update(payment);
        //再修改订单表
        BookingOrder bookingOrder= BookingOrder.builder()
                .orderId(payment1.getOrderId())
                .paymentStatus("已支付")
                .build();
        bookingOrderMapper.update(bookingOrder);
        //修改会议室的状态为空闲
        BookingOrder bookingOrder1=bookingOrderMapper.getById(payment1.getOrderId());
        MeetingRoom meetingRoom=MeetingRoom.builder()
                .id(bookingOrder1.getMeetingRoomId())
                .status("空闲")
                .build();
        meetingRoomMapper.update(meetingRoom);
    }


    /**
     * 退款申请
     * @param orderId
     */
    @Override
    public String refund(Long orderId) {
        // 根据支付记录 ID 获取支付信息
        Payment payment = paymentMapper.getByOrderId(orderId);
        if (payment == null) {
            throw new PaymentNotFoundException("订单记录不存在");
        }
        BookingOrder bookingOrder1=bookingOrderMapper.getById(payment.getOrderId());
        // 获取当前时间和预定的起始时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime bookingStartTime = bookingOrder1.getBookingStartTime();

        // 计算开始时间和当前时间之间的差值（分钟）
        long minutesBetween = Math.abs(ChronoUnit.MINUTES.between(bookingStartTime, now));

        System.out.println("距离预定开始时间为"+minutesBetween);

        // 根据时间差判定退款比例
        double refundPercentage = getRefundPercentage(minutesBetween);

        System.out.println("退款比例为"+refundPercentage);

        // 计算可退款金额
        BookingOrder bookingOrder=bookingOrderMapper.getById(payment.getOrderId());
        double refundAmount=refundPercentage*bookingOrder.getTotalPrice();
        System.out.println("可退款金额为"+refundAmount);

        // 更新支付记录状态为退款中
        payment.setPaymentStatus("退款中");
        paymentMapper.update(payment);

        System.out.println("退款申请已提交，可退款金额：" + refundAmount);

        // 将分钟转换为小时和分钟
        long hours = minutesBetween / 60;
        long minutes = minutesBetween % 60;
        // 构建返回信息
        return String.format("距离会议开始时间还有：%d小时%d分钟，可退款金额为：%.2f元", hours, minutes, refundAmount);
    }
    /**
     * 根据时间差（分钟）判定退款比例
     * @param minutesBetween 支付时间和当前时间之间的差值（分钟）
     * @return 退款比例
     */
    private double getRefundPercentage(long minutesBetween) {
        if (minutesBetween >= 4320) { // 72小时 = 72 * 60 = 4320分钟
            return 1.0; // 72小时以上，退全款
        } else if (minutesBetween >= 2880) { // 48小时 = 48 * 60 = 2880分钟
            return 0.75; // 48-72小时，退75%
        } else if (minutesBetween >= 1440) { // 24小时 = 24 * 60 = 1440分钟
            return 0.25; // 24-48小时，退25%
        } else {
            throw new OutTimeException("时间小于24小时，无法退款");
        }
    }


    /**
     * 用户取消订单或者超时取消订单
     * @param orderId
     */
    @Override
    public void cancelOrder(Long orderId) {
        Payment payment=paymentMapper.getByOrderId(orderId);
        //修改booking表
        BookingOrder bookingOrder=BookingOrder.builder()
                .orderId(payment.getOrderId())
                .paymentStatus("已取消")
                .build();
        bookingOrderMapper.update(bookingOrder);
        //修改payment表
        payment.setPaymentStatus("已取消");
        paymentMapper.update(payment);

        //修改会议室的状态为空闲
        BookingOrder bookingOrder1=bookingOrderMapper.getById(payment.getOrderId());
        MeetingRoom meetingRoom=MeetingRoom.builder()
                .id(bookingOrder1.getMeetingRoomId())
                .status("空闲")
                .build();
        meetingRoomMapper.update(meetingRoom);
    }


    /**
     * 根据用户ID查询所有订单
     * @return 订单列表
     */
    @Override
    public List<OrderVO> getAllOrdersByUserId() {
        Long userId = BaseContext.getCurrentId();
        //更新订单状态——超时的直接变为取消
        paymentMapper.updateOutTimeOrders(userId);
        return bookingOrderMapper.getAllOrdersByUserId(userId);
    }


    /**
     * 返回这个用户的所有订单中可以退款的记录
     * @return
     */
    @Override
    public List<OrderVO> getPaidOrders() {
        List<OrderVO> orderVOList=bookingOrderMapper.getAllOrdersByUserId(BaseContext.getCurrentId());
        // 当前时间
        LocalDateTime now = LocalDateTime.now();

        // 筛选距离当前时间大于等于24小时的订单
        List<OrderVO> filteredOrders = orderVOList.stream()
                .filter(order -> {
                    // 判断订单状态是否为“已支付”
                    if (!"已支付".equals(order.getPaymentStatus())) {
                        return false;
                    }
                    LocalDateTime bookingStartTime = order.getBookingStartTime();
                    if (bookingStartTime == null) {
                        return false;
                    }
                    long minutesBetween = ChronoUnit.MINUTES.between(now, bookingStartTime);
                    return minutesBetween >= 1440; // 24小时 = 1440分钟
                })
                .collect(Collectors.toList());

        return filteredOrders;
    }

    /**
     * 查看可退款金额
     * @param orderId
     * @return
     */
    @Override
    public String queryRefundableAmount(Long orderId) {
        // 根据支付记录 ID 获取支付信息
        Payment payment = paymentMapper.getByOrderId(orderId);
        if (payment == null) {
            throw new PaymentNotFoundException("订单记录不存在");
        }
        BookingOrder bookingOrder1=bookingOrderMapper.getById(payment.getOrderId());
        // 获取当前时间和预定的起始时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime bookingStartTime = bookingOrder1.getBookingStartTime();

        // 计算开始时间和当前时间之间的差值（分钟）
        long minutesBetween = Math.abs(ChronoUnit.MINUTES.between(bookingStartTime, now));

        System.out.println("距离预定开始时间为"+minutesBetween);

        // 根据时间差判定退款比例
        double refundPercentage = getRefundPercentage(minutesBetween);

        System.out.println("退款比例为"+refundPercentage);

        // 计算可退款金额
        BookingOrder bookingOrder=bookingOrderMapper.getById(payment.getOrderId());
        double refundAmount=refundPercentage*bookingOrder.getTotalPrice();
        System.out.println("可退款金额为"+refundAmount);

        // 将分钟转换为小时和分钟
        long hours = minutesBetween / 60;
        long minutes = minutesBetween % 60;
        // 构建返回信息
        return String.format("距离会议开始时间还有：%d小时%d分钟，可退款金额为：%.2f元，退款比例为"+refundPercentage, hours, minutes, refundAmount);
    }
}
